package com.free4inno.knowledgems.utils;

import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.InnerHitsContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Author LIUXINYUAN.
 * Date 2022/4/3 22:38.
 */

public class HighlightResultMapper implements SearchResultMapper {
    @Override
    public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> clazz, Pageable pageable) {
        long totalHits = searchResponse.getHits().getTotalHits();
        List<T> list = new ArrayList<>();
        SearchHits hits = searchResponse.getHits();
        if (hits.getHits().length> 0) {
            for (SearchHit searchHit : hits) { //遍历hits
                Map<String, HighlightField> highlightFields = searchHit.getHighlightFields(); //取出该条文档的highlight
                Map<String, SearchHits> innerHitsContent = searchHit.getInnerHits(); //取出该条文档的highlight
                T item = JSON.parseObject(searchHit.getSourceAsString(), clazz); //解析除highlight的其他属性
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    //为highlight属性赋值，用于标记命中位置
                    if (field.getName().equals("highlight")) {
                        try {
                            field.set(item,highlightFields);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    //为innerHits属性赋值，用于标记命中位置
                    if (field.getName().equals("innerHitsContent")) {
                        try {
                            field.set(item,innerHitsContent);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
                list.add(item);
            }
        }
        return new AggregatedPageImpl<>(list, pageable, totalHits);
    }
}